using System.Collections.Immutable;
using System.Diagnostics;
using DimensionsHelper.LanguageService.Symbols;
using DimensionsHelper.LanguageService.Syntax;

namespace DimensionsHelper.LanguageService;

public class AnalysisUnary : AnalysisExpression
{
    internal AnalysisUnary(UnaryExpression syntaxNode, AnalysisNode? parent) : base(AnalysisBoundKinds.Unary,
        syntaxNode, parent)
    {
        Syntax = syntaxNode;
    }

    private AnalysisExpression? _expression;

    public override UnaryExpression Syntax { get; }

    public override int ChildrenCount => 1;

    public override IEnumerable<AnalysisNode> GetChildren()
    {
        return _expression != null ? [_expression] : ImmutableArray<AnalysisNode>.Empty;
    }

    internal override void AddChild(AnalysisNode child)
    {
        Debug.Assert(child.IsExpression);
        Debug.Assert(_expression == null, "Unary expression already has an expression.");
        child.Parent = this;
        _expression = (AnalysisExpression)child;
    }

    public override AnalysisExpression? WithImplicitlyConversion(ValueTypeSymbol targetType)
    {
        // Not
        if (Syntax.Operator.IsNode(SyntaxKinds.NotKeywordToken) &&
            targetType.IsAssignableFrom(ValueTypeSymbol.Boolean))
        {
            return this;
        }
        
        // -
        if (Syntax.Operator.IsNode(SyntaxKinds.MinusToken) && _expression != null)
        {
            var expressionSymbol = _expression.GetTypeSymbol().GetFinalBindableBindingOrThis();
            // Any | Null | Undefined 视为整数
            if ((ValueTypeSymbol.IsAnyOrNull(expressionSymbol) || expressionSymbol.IsUndefined) &&
                targetType.IsAssignableFrom(ValueTypeSymbol.Long))
            {
                return this;
            }
            // Long
            if (ValueTypeSymbol.IsLong(expressionSymbol) &&
                targetType.IsAssignableFrom(ValueTypeSymbol.Long))
            {
                return this;
            }
            // Double
            if (ValueTypeSymbol.IsDouble(expressionSymbol) &&
                targetType.IsAssignableFrom(ValueTypeSymbol.Double))
            {
                return this;
            }
        }

        return null;
    }
}


public static partial class AnalysisNodeFactory
{
    /// <summary>
    /// 创建一个单目表达式。
    /// </summary>
    /// <param name="syntaxNode">原始语法节点</param>
    /// <param name="parent">父节点，可以忽略</param>
    /// <param name="withSymbol">此节点所处的With语句上下文类型符号</param>
    /// <param name="expression">语法表达式</param>
    public static AnalysisUnary Unary(UnaryExpression syntaxNode, AnalysisNode? parent, ITypeSymbol? withSymbol,
        AnalysisExpression? expression = null)
    {
        AnalysisUnary binary = new(syntaxNode, parent);

        if (expression != null)
        {
            binary.AddChild(expression);
        }

        return binary.WithContainingWithSymbol(withSymbol);
    }
}

